package org.bouncycastle.jce;

import java.io.IOException;
import java.security.AlgorithmParameters;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PSSParameterSpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Set;

import javax.security.auth.x500.X500Principal;

import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1Set;
import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.DEREncodable;
import org.bouncycastle.asn1.DERInteger;
import org.bouncycastle.asn1.DERNull;
import org.bouncycastle.asn1.DERObjectIdentifier;
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.CertificationRequest;
import org.bouncycastle.asn1.pkcs.CertificationRequestInfo;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.RSASSAPSSparams;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.asn1.x509.X509Name;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.Strings;

/**
 * A class for verifying and creating PKCS10 Certification requests.
 * 
 * <pre>
 * CertificationRequest ::= SEQUENCE {
 *   certificationRequestInfo  CertificationRequestInfo,
 *   signatureAlgorithm        AlgorithmIdentifier{{ SignatureAlgorithms }},
 *   signature                 BIT STRING
 * }
 * 
 * CertificationRequestInfo ::= SEQUENCE {
 *   version             INTEGER { v1(0) } (v1,...),
 *   subject             Name,
 *   subjectPKInfo   SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
 *   attributes          [0] Attributes{{ CRIAttributes }}
 *  }
 * 
 *  Attributes { ATTRIBUTE:IOSet } ::= SET OF Attribute{{ IOSet }}
 * 
 *  Attribute { ATTRIBUTE:IOSet } ::= SEQUENCE {
 *    type    ATTRIBUTE.&id({IOSet}),
 *    values  SET SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{\@type})
 *  }
 * </pre>
 */
@SuppressWarnings({ "rawtypes", "unchecked", "deprecation" })
public class PKCS10CertificationRequest extends CertificationRequest {
    private static Hashtable algorithms = new Hashtable();
    private static Hashtable params = new Hashtable();
    private static Hashtable keyAlgorithms = new Hashtable();
    private static Hashtable oids = new Hashtable();
    private static Set noParams = new HashSet();

    static {
        // BEGIN android-removed
        // Dropping MD2
        // algorithms.put("MD2WITHRSAENCRYPTION", new
        // DERObjectIdentifier("1.2.840.113549.1.1.2"));
        // algorithms.put("MD2WITHRSA", new
        // DERObjectIdentifier("1.2.840.113549.1.1.2"));
        // END android-removed
        algorithms.put("MD5WITHRSAENCRYPTION", new DERObjectIdentifier(
                "1.2.840.113549.1.1.4"));
        algorithms.put("MD5WITHRSA", new DERObjectIdentifier(
                "1.2.840.113549.1.1.4"));
        algorithms.put("RSAWITHMD5", new DERObjectIdentifier(
                "1.2.840.113549.1.1.4"));
        algorithms.put("SHA1WITHRSAENCRYPTION", new DERObjectIdentifier(
                "1.2.840.113549.1.1.5"));
        algorithms.put("SHA1WITHRSA", new DERObjectIdentifier(
                "1.2.840.113549.1.1.5"));
        // BEGIN android-removed
        // algorithms.put("SHA224WITHRSAENCRYPTION",
        // PKCSObjectIdentifiers.sha224WithRSAEncryption);
        // algorithms.put("SHA224WITHRSA",
        // PKCSObjectIdentifiers.sha224WithRSAEncryption);
        // END android-removed
        algorithms.put("SHA256WITHRSAENCRYPTION",
                PKCSObjectIdentifiers.sha256WithRSAEncryption);
        algorithms.put("SHA256WITHRSA",
                PKCSObjectIdentifiers.sha256WithRSAEncryption);
        algorithms.put("SHA384WITHRSAENCRYPTION",
                PKCSObjectIdentifiers.sha384WithRSAEncryption);
        algorithms.put("SHA384WITHRSA",
                PKCSObjectIdentifiers.sha384WithRSAEncryption);
        algorithms.put("SHA512WITHRSAENCRYPTION",
                PKCSObjectIdentifiers.sha512WithRSAEncryption);
        algorithms.put("SHA512WITHRSA",
                PKCSObjectIdentifiers.sha512WithRSAEncryption);
        algorithms.put("SHA1WITHRSAANDMGF1",
                PKCSObjectIdentifiers.id_RSASSA_PSS);
        // BEGIN android-removed
        // algorithms.put("SHA224WITHRSAANDMGF1",
        // PKCSObjectIdentifiers.id_RSASSA_PSS);
        // END android-removed
        algorithms.put("SHA256WITHRSAANDMGF1",
                PKCSObjectIdentifiers.id_RSASSA_PSS);
        algorithms.put("SHA384WITHRSAANDMGF1",
                PKCSObjectIdentifiers.id_RSASSA_PSS);
        algorithms.put("SHA512WITHRSAANDMGF1",
                PKCSObjectIdentifiers.id_RSASSA_PSS);
        algorithms.put("RSAWITHSHA1", new DERObjectIdentifier(
                "1.2.840.113549.1.1.5"));
        // BEGIN android-removed
        // algorithms.put("RIPEMD128WITHRSAENCRYPTION",
        // TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128);
        // algorithms.put("RIPEMD128WITHRSA",
        // TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128);
        // algorithms.put("RIPEMD160WITHRSAENCRYPTION",
        // TeleTrusTObjectIdentifiers.rsaSignatureWithripemd160);
        // algorithms.put("RIPEMD160WITHRSA",
        // TeleTrusTObjectIdentifiers.rsaSignatureWithripemd160);
        // algorithms.put("RIPEMD256WITHRSAENCRYPTION",
        // TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256);
        // algorithms.put("RIPEMD256WITHRSA",
        // TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256);
        // END android-removed
        algorithms.put("SHA1WITHDSA", new DERObjectIdentifier(
                "1.2.840.10040.4.3"));
        algorithms.put("DSAWITHSHA1", new DERObjectIdentifier(
                "1.2.840.10040.4.3"));
        // BEGIN android-removed
        // algorithms.put("SHA224WITHDSA",
        // NISTObjectIdentifiers.dsa_with_sha224);
        // END android-removed
        algorithms.put("SHA256WITHDSA", NISTObjectIdentifiers.dsa_with_sha256);
        algorithms.put("SHA384WITHDSA", NISTObjectIdentifiers.dsa_with_sha384);
        algorithms.put("SHA512WITHDSA", NISTObjectIdentifiers.dsa_with_sha512);
        algorithms.put("SHA1WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA1);
        // BEGIN android-removed
        // algorithms.put("SHA224WITHECDSA",
        // X9ObjectIdentifiers.ecdsa_with_SHA224);
        // END android-removed
        algorithms
                .put("SHA256WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA256);
        algorithms
                .put("SHA384WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA384);
        algorithms
                .put("SHA512WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA512);
        algorithms.put("ECDSAWITHSHA1", X9ObjectIdentifiers.ecdsa_with_SHA1);
        // BEGIN android-removed
        // algorithms.put("GOST3411WITHGOST3410",
        // CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94);
        // algorithms.put("GOST3410WITHGOST3411",
        // CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94);
        // algorithms.put("GOST3411WITHECGOST3410",
        // CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001);
        // algorithms.put("GOST3411WITHECGOST3410-2001",
        // CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001);
        // algorithms.put("GOST3411WITHGOST3410-2001",
        // CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001);
        // END android-removed

        //
        // reverse mappings
        //
        oids.put(new DERObjectIdentifier("1.2.840.113549.1.1.5"), "SHA1WITHRSA");
        // BEGIN android-removed
        // oids.put(PKCSObjectIdentifiers.sha224WithRSAEncryption,
        // "SHA224WITHRSA");
        // END android-removed
        oids.put(PKCSObjectIdentifiers.sha256WithRSAEncryption, "SHA256WITHRSA");
        oids.put(PKCSObjectIdentifiers.sha384WithRSAEncryption, "SHA384WITHRSA");
        oids.put(PKCSObjectIdentifiers.sha512WithRSAEncryption, "SHA512WITHRSA");
        // BEGIN android-removed
        // oids.put(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94,
        // "GOST3411WITHGOST3410");
        // oids.put(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001,
        // "GOST3411WITHECGOST3410");
        // END android-removed

        oids.put(new DERObjectIdentifier("1.2.840.113549.1.1.4"), "MD5WITHRSA");
        // BEGIN android-removed
        // Dropping MD2
        // oids.put(new DERObjectIdentifier("1.2.840.113549.1.1.2"),
        // "MD2WITHRSA");
        // END android-removed
        oids.put(new DERObjectIdentifier("1.2.840.10040.4.3"), "SHA1WITHDSA");
        oids.put(X9ObjectIdentifiers.ecdsa_with_SHA1, "SHA1WITHECDSA");
        // BEGIN android-removed
        // oids.put(X9ObjectIdentifiers.ecdsa_with_SHA224, "SHA224WITHECDSA");
        // END android-removed
        oids.put(X9ObjectIdentifiers.ecdsa_with_SHA256, "SHA256WITHECDSA");
        oids.put(X9ObjectIdentifiers.ecdsa_with_SHA384, "SHA384WITHECDSA");
        oids.put(X9ObjectIdentifiers.ecdsa_with_SHA512, "SHA512WITHECDSA");
        oids.put(OIWObjectIdentifiers.sha1WithRSA, "SHA1WITHRSA");
        oids.put(OIWObjectIdentifiers.dsaWithSHA1, "SHA1WITHDSA");
        // BEGIN android-removed
        // oids.put(NISTObjectIdentifiers.dsa_with_sha224, "SHA224WITHDSA");
        // END android-removed
        oids.put(NISTObjectIdentifiers.dsa_with_sha256, "SHA256WITHDSA");

        //
        // key types
        //
        keyAlgorithms.put(PKCSObjectIdentifiers.rsaEncryption, "RSA");
        keyAlgorithms.put(X9ObjectIdentifiers.id_dsa, "DSA");

        //
        // According to RFC 3279, the ASN.1 encoding SHALL (id-dsa-with-sha1) or
        // MUST (ecdsa-with-SHA*) omit the parameters field.
        // The parameters field SHALL be NULL for RSA based signature
        // algorithms.
        //
        noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA1);
        // BEGIN android-removed
        // noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA224);
        // END android-removed
        noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA256);
        noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA384);
        noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA512);
        noParams.add(X9ObjectIdentifiers.id_dsa_with_sha1);
        // BEGIN android-removed
        // noParams.add(NISTObjectIdentifiers.dsa_with_sha224);
        // END android-removed
        noParams.add(NISTObjectIdentifiers.dsa_with_sha256);

        //
        // RFC 4491
        //
        // BEGIN android-removed
        // noParams.add(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94);
        // noParams.add(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001);
        // END android-removed
        //
        // explicit params
        //
        // BEGIN android-changed
        AlgorithmIdentifier sha1AlgId = new AlgorithmIdentifier(
                OIWObjectIdentifiers.idSHA1, DERNull.INSTANCE);
        // END android-changed
        params.put("SHA1WITHRSAANDMGF1", creatPSSParams(sha1AlgId, 20));

        // BEGIN android-removed
        // // BEGIN android-changed
        // AlgorithmIdentifier sha224AlgId = new
        // AlgorithmIdentifier(NISTObjectIdentifiers.id_sha224,
        // DERNull.INSTANCE);
        // // END android-changed
        // params.put("SHA224WITHRSAANDMGF1", creatPSSParams(sha224AlgId, 28));
        // END android-removed

        // BEGIN android-changed
        AlgorithmIdentifier sha256AlgId = new AlgorithmIdentifier(
                NISTObjectIdentifiers.id_sha256, DERNull.INSTANCE);
        // END android-changed
        params.put("SHA256WITHRSAANDMGF1", creatPSSParams(sha256AlgId, 32));

        // BEGIN android-changed
        AlgorithmIdentifier sha384AlgId = new AlgorithmIdentifier(
                NISTObjectIdentifiers.id_sha384, DERNull.INSTANCE);
        // END android-changed
        params.put("SHA384WITHRSAANDMGF1", creatPSSParams(sha384AlgId, 48));

        // BEGIN android-changed
        AlgorithmIdentifier sha512AlgId = new AlgorithmIdentifier(
                NISTObjectIdentifiers.id_sha512, DERNull.INSTANCE);
        // END android-changed
        params.put("SHA512WITHRSAANDMGF1", creatPSSParams(sha512AlgId, 64));
    }

    private static RSASSAPSSparams creatPSSParams(
            AlgorithmIdentifier hashAlgId, int saltSize) {
        return new RSASSAPSSparams(hashAlgId, new AlgorithmIdentifier(
                PKCSObjectIdentifiers.id_mgf1, hashAlgId), new DERInteger(
                saltSize), new DERInteger(1));
    }

    private static ASN1Sequence toDERSequence(byte[] bytes) {
        try {
            ASN1InputStream dIn = new ASN1InputStream(bytes);

            return (ASN1Sequence) dIn.readObject();
        } catch (Exception e) {
            throw new IllegalArgumentException("badly encoded request");
        }
    }

    /**
     * construct a PKCS10 certification request from a DER encoded byte stream.
     */
    public PKCS10CertificationRequest(byte[] bytes) {
        super(toDERSequence(bytes));
    }

    public PKCS10CertificationRequest(ASN1Sequence sequence) {
        super(sequence);
    }

    /**
     * create a PKCS10 certfication request using the BC provider.
     */
    public PKCS10CertificationRequest(String signatureAlgorithm,
            X509Name subject, PublicKey key, ASN1Set attributes,
            PrivateKey signingKey) throws NoSuchAlgorithmException,
            NoSuchProviderException, InvalidKeyException, SignatureException {
        this(signatureAlgorithm, subject, key, attributes, signingKey,
                BouncyCastleProvider.PROVIDER_NAME);
    }

    private static X509Name convertName(X500Principal name) {
        try {
            return new X509Principal(name.getEncoded());
        } catch (IOException e) {
            throw new IllegalArgumentException("can't convert name");
        }
    }

    /**
     * create a PKCS10 certfication request using the BC provider.
     */
    public PKCS10CertificationRequest(String signatureAlgorithm,
            X500Principal subject, PublicKey key, ASN1Set attributes,
            PrivateKey signingKey) throws NoSuchAlgorithmException,
            NoSuchProviderException, InvalidKeyException, SignatureException {
        this(signatureAlgorithm, convertName(subject), key, attributes,
                signingKey, BouncyCastleProvider.PROVIDER_NAME);
    }

    /**
     * create a PKCS10 certfication request using the named provider.
     */
    public PKCS10CertificationRequest(String signatureAlgorithm,
            X500Principal subject, PublicKey key, ASN1Set attributes,
            PrivateKey signingKey, String provider)
            throws NoSuchAlgorithmException, NoSuchProviderException,
            InvalidKeyException, SignatureException {
        this(signatureAlgorithm, convertName(subject), key, attributes,
                signingKey, provider);
    }

    /**
     * create a PKCS10 certfication request using the named provider.
     */
    public PKCS10CertificationRequest(String signatureAlgorithm,
            X509Name subject, PublicKey key, ASN1Set attributes,
            PrivateKey signingKey, String provider)
            throws NoSuchAlgorithmException, NoSuchProviderException,
            InvalidKeyException, SignatureException {
        String algorithmName = Strings.toUpperCase(signatureAlgorithm);
        DERObjectIdentifier sigOID = (DERObjectIdentifier) algorithms
                .get(algorithmName);

        if (sigOID == null) {
            try {
                sigOID = new DERObjectIdentifier(algorithmName);
            } catch (Exception e) {
                throw new IllegalArgumentException(
                        "Unknown signature type requested");
            }
        }

        if (subject == null) {
            throw new IllegalArgumentException("subject must not be null");
        }

        if (key == null) {
            throw new IllegalArgumentException("public key must not be null");
        }

        if (noParams.contains(sigOID)) {
            this.sigAlgId = new AlgorithmIdentifier(sigOID);
        } else if (params.containsKey(algorithmName)) {
            this.sigAlgId = new AlgorithmIdentifier(sigOID,
                    (DEREncodable) params.get(algorithmName));
        } else {
            this.sigAlgId = new AlgorithmIdentifier(sigOID, DERNull.INSTANCE);
        }

        try {
            ASN1Sequence seq = (ASN1Sequence) ASN1Object.fromByteArray(key
                    .getEncoded());
            this.reqInfo = new CertificationRequestInfo(subject,
                    new SubjectPublicKeyInfo(seq), attributes);
        } catch (IOException e) {
            throw new IllegalArgumentException("can't encode public key");
        }

        Signature sig;
        if (provider == null) {
            sig = Signature.getInstance(signatureAlgorithm);
        } else {
            sig = Signature.getInstance(signatureAlgorithm, provider);
        }

        sig.initSign(signingKey);

        try {
            sig.update(reqInfo.getEncoded(ASN1Encodable.DER));
        } catch (Exception e) {
            throw new IllegalArgumentException(
                    "exception encoding TBS cert request - " + e);
        }

        this.sigBits = new DERBitString(sig.sign());
    }

    /**
     * return the public key associated with the certification request - the
     * public key is created using the BC provider.
     */
    public PublicKey getPublicKey() throws NoSuchAlgorithmException,
            NoSuchProviderException, InvalidKeyException {
        return getPublicKey(BouncyCastleProvider.PROVIDER_NAME);
    }

    public PublicKey getPublicKey(String provider)
            throws NoSuchAlgorithmException, NoSuchProviderException,
            InvalidKeyException {
        SubjectPublicKeyInfo subjectPKInfo = reqInfo.getSubjectPublicKeyInfo();
        X509EncodedKeySpec xspec = new X509EncodedKeySpec(new DERBitString(
                subjectPKInfo).getBytes());
        AlgorithmIdentifier keyAlg = subjectPKInfo.getAlgorithmId();

        try {
            try {
                if (provider == null) {
                    return KeyFactory.getInstance(keyAlg.getObjectId().getId())
                            .generatePublic(xspec);
                } else {
                    return KeyFactory.getInstance(keyAlg.getObjectId().getId(),
                            provider).generatePublic(xspec);
                }
            } catch (NoSuchAlgorithmException e) {
                //
                // try an alternate
                //
                if (keyAlgorithms.get(keyAlg.getObjectId()) != null) {
                    String keyAlgorithm = (String) keyAlgorithms.get(keyAlg
                            .getObjectId());

                    if (provider == null) {
                        return KeyFactory.getInstance(keyAlgorithm)
                                .generatePublic(xspec);
                    } else {
                        return KeyFactory.getInstance(keyAlgorithm, provider)
                                .generatePublic(xspec);
                    }
                }

                throw e;
            }
        } catch (InvalidKeySpecException e) {
            throw new InvalidKeyException("error decoding public key");
        }
    }

    /**
     * verify the request using the BC provider.
     */
    public boolean verify() throws NoSuchAlgorithmException,
            NoSuchProviderException, InvalidKeyException, SignatureException {
        return verify(BouncyCastleProvider.PROVIDER_NAME);
    }

    /**
     * verify the request using the passed in provider.
     */
    public boolean verify(String provider) throws NoSuchAlgorithmException,
            NoSuchProviderException, InvalidKeyException, SignatureException {
        return verify(this.getPublicKey(provider), provider);
    }

    /**
     * verify the request using the passed in public key and the provider..
     */
    public boolean verify(PublicKey pubKey, String provider)
            throws NoSuchAlgorithmException, NoSuchProviderException,
            InvalidKeyException, SignatureException {
        Signature sig;

        try {
            if (provider == null) {
                sig = Signature.getInstance(getSignatureName(sigAlgId));
            } else {
                sig = Signature.getInstance(getSignatureName(sigAlgId),
                        provider);
            }
        } catch (NoSuchAlgorithmException e) {
            //
            // try an alternate
            //
            if (oids.get(sigAlgId.getObjectId()) != null) {
                String signatureAlgorithm = (String) oids.get(sigAlgId
                        .getObjectId());

                if (provider == null) {
                    sig = Signature.getInstance(signatureAlgorithm);
                } else {
                    sig = Signature.getInstance(signatureAlgorithm, provider);
                }
            } else {
                throw e;
            }
        }

        setSignatureParameters(sig, sigAlgId.getParameters());

        sig.initVerify(pubKey);

        try {
            sig.update(reqInfo.getEncoded(ASN1Encodable.DER));
        } catch (Exception e) {
            throw new SignatureException(
                    "exception encoding TBS cert request - " + e);
        }

        return sig.verify(sigBits.getBytes());
    }

    /**
     * return a DER encoded byte array representing this object
     */
    public byte[] getEncoded() {
        try {
            return this.getEncoded(ASN1Encodable.DER);
        } catch (IOException e) {
            throw new RuntimeException(e.toString());
        }
    }

    private void setSignatureParameters(Signature signature, DEREncodable params)
            throws NoSuchAlgorithmException, SignatureException,
            InvalidKeyException {
        if (params != null && !DERNull.INSTANCE.equals(params)) {
            AlgorithmParameters sigParams = AlgorithmParameters.getInstance(
                    signature.getAlgorithm(), signature.getProvider());

            try {
                sigParams.init(params.getDERObject().getDEREncoded());
            } catch (IOException e) {
                throw new SignatureException(
                        "IOException decoding parameters: " + e.getMessage());
            }

            if (signature.getAlgorithm().endsWith("MGF1")) {
                try {
                    signature.setParameter(sigParams
                            .getParameterSpec(PSSParameterSpec.class));
                } catch (GeneralSecurityException e) {
                    throw new SignatureException(
                            "Exception extracting parameters: "
                                    + e.getMessage());
                }
            }
        }
    }

    static String getSignatureName(AlgorithmIdentifier sigAlgId) {
        DEREncodable params = sigAlgId.getParameters();

        if (params != null && !DERNull.INSTANCE.equals(params)) {
            if (sigAlgId.getObjectId().equals(
                    PKCSObjectIdentifiers.id_RSASSA_PSS)) {
                RSASSAPSSparams rsaParams = RSASSAPSSparams.getInstance(params);
                return getDigestAlgName(rsaParams.getHashAlgorithm()
                        .getObjectId()) + "withRSAandMGF1";
            }
        }

        return sigAlgId.getObjectId().getId();
    }

    private static String getDigestAlgName(DERObjectIdentifier digestAlgOID) {
        if (PKCSObjectIdentifiers.md5.equals(digestAlgOID)) {
            return "MD5";
        } else if (OIWObjectIdentifiers.idSHA1.equals(digestAlgOID)) {
            return "SHA1";
        }
        // BEGIN android-removed
        // else if (NISTObjectIdentifiers.id_sha224.equals(digestAlgOID))
        // {
        // return "SHA224";
        // }
        // END android-removed
        else if (NISTObjectIdentifiers.id_sha256.equals(digestAlgOID)) {
            return "SHA256";
        } else if (NISTObjectIdentifiers.id_sha384.equals(digestAlgOID)) {
            return "SHA384";
        } else if (NISTObjectIdentifiers.id_sha512.equals(digestAlgOID)) {
            return "SHA512";
        }
        // BEGIN android-removed
        // else if (TeleTrusTObjectIdentifiers.ripemd128.equals(digestAlgOID))
        // {
        // return "RIPEMD128";
        // }
        // else if (TeleTrusTObjectIdentifiers.ripemd160.equals(digestAlgOID))
        // {
        // return "RIPEMD160";
        // }
        // else if (TeleTrusTObjectIdentifiers.ripemd256.equals(digestAlgOID))
        // {
        // return "RIPEMD256";
        // }
        // else if (CryptoProObjectIdentifiers.gostR3411.equals(digestAlgOID))
        // {
        // return "GOST3411";
        // }
        // END android-removed
        else {
            return digestAlgOID.getId();
        }
    }
}
